package com.livestocksolutions.util;

import java.util.Comparator;

import com.livestocksolutions.Bovine;
import com.livestocksolutions.Group;
import com.livestocksolutions.Join;
import com.livestocksolutions.Location;
import com.livestocksolutions.MedicalHistory;
import com.livestocksolutions.Mob;
import com.livestocksolutions.Observation;
import com.livestocksolutions.Owner;
import com.livestocksolutions.Paddock;
import com.livestocksolutions.UsableItem;
import com.livestocksolutions.UsableItemHistory;
import com.livestocksolutions.Weight;

/*
 * This class is a common class between Android and Java.
 * Android Comparator does not like the annotation of @Override
 * being used on the Overridden compare(T,T) methods and sees these
 * as errors, Java sees the removal of the annotation @Override as
 * only a warning. Any warnings that may appear are because of that.
 */
@SuppressWarnings(value={"all"}) 
/**
 * List of Comparators that are used to sort lists of these specified Objects
 * @author Adam Parr
 * @author Matt Lang
 *
 *@.modified 07 January 2013
 */
public class Comparators {
	/**
	 * Compare a list of Cattle
	 */
	public static Comparator<Bovine> bovineOffspringAveSellPrice = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
			if(first.getOffspringAverageSellPrice() < second.getOffspringAverageSellPrice())
				return 1;
			else if(first.getOffspringAverageSellPrice() > second.getOffspringAverageSellPrice())
				return -1;
			else
				return 0;
		}
	};
	
	/**
	 * A comparator for comparing Bovine animals by DOB.
	 */
	public static Comparator<Bovine> bovineComparatorDOB = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
	    	if(second.getDob()!=null && first.getDob()==null){
	    		return 1;
	    	}else if(second.getDob()==null && first.getDob()==null){
	    		return 0;
	    	}else if(second.getDob()==null && first.getDob()!=null){
	    		return -1;
	    	}else{
	    		return ((Long)second.getDob().getTime()).compareTo(first.getDob().getTime());
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Bovine animals by number of Offspring.
	 */
	public static Comparator<Bovine> bovineNumberOffspringComparator = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
			return ((Integer)second.getOffspring().length).compareTo(first.getOffspring().length);
		}
	};
	
	/**
	 * Comparator for bovines offspring average weight gain
	 */
	public static Comparator<Bovine> bovineOffspringAverageWeightGain = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
			return ((Double)first.getOffspringAverageDailyGrowth()).compareTo(second.getOffspringAverageDailyGrowth());
		}
	};
	
	/**
	 * comparator for bovines total average weight gain
	 */
	public static Comparator<Bovine> bovineAverageWeightGain = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
			return ((Double)first.getAverageDailyGrowth()).compareTo(second.getAverageDailyGrowth());
		}
	};
	
	/**
	 * A comparator for comparing Bovine animals by Visual ID.
	 */
	public static Comparator<Bovine> bovineComparatorVISID = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
	    	if(first.getEartag().getEartagID()!=null && second.getEartag().getEartagID()==null){
	    		return 1;
	    	}else if(first.getEartag().getEartagID()==null && second.getEartag().getEartagID()==null){
	    		return 0;
	    	}else if(first.getEartag().getEartagID()==null && second.getEartag().getEartagID()!=null){
	    		return -1;
	    	}else{
	    		return (first.getEartag().getEartagID()).compareTo(second.getEartag().getEartagID());
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Bovine animals by NLIS ID.
	 */
	public static Comparator<Bovine> bovineComparatorNLISID = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
	    	if(first.getEartag().getNlisID()!=null && second.getEartag().getNlisID()==null){
	    		return 1;
	    	}else if(first.getEartag().getNlisID()==null && second.getEartag().getNlisID()==null){
	    		return 0;
	    	}else if(first.getEartag().getNlisID()==null && second.getEartag().getNlisID()!=null){
	    		return -1;
	    	}else{
	    		return (first.getEartag().getNlisID()).compareTo(second.getEartag().getNlisID());
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Bovine animals by RFID ID.
	 */
	public static Comparator<Bovine> bovineComparatorRFID = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
	    	if(first.getEartag().getRfID()!=null && second.getEartag().getRfID()==null){
	    		return 1;
	    	}else if(first.getEartag().getRfID()==null && second.getEartag().getRfID()==null){
	    		return 0;
	    	}else if(first.getEartag().getRfID()==null && second.getEartag().getRfID()!=null){
	    		return -1;
	    	}else{
	    		return (first.getEartag().getRfID()).compareTo(second.getEartag().getRfID());
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Bovine animals by Active Status.
	 */
	public static Comparator<Bovine> bovineComparatorActive = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
	    	if(first.isActive() && !second.isActive()){
	    		return 1;
	    	}else if(first.isActive() && second.isActive()){
	    		return 0;
	    	}else{
	    		return -1;
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Bovine animals by Gender.
	 */
	public static Comparator<Bovine> bovineComparatorGender = new Comparator<Bovine>(){
		public int compare(final Bovine first, final Bovine second){
	    	return first.getGender().compareTo(second.getGender());
	    }
	};
	
	/*
	 * Compare a list of Groups/Mobs
	 */
	/**
	 * A comparator for comparing Groups by Name.
	 */
	public static Comparator<Group> groupComparatorName = new Comparator<Group>(){
		public int compare(final Group first, final Group second){
	    	return (first.getName()).compareTo(second.getName());
	    }
	};
	
	/**
	 * A comparator for comparing Mobs by Name.
	 */
	public static Comparator<Mob> mobComparatorName = new Comparator<Mob>(){
		public int compare(final Mob first, final Mob second){
	    	return (first.getName()).compareTo(second.getName());
	    }
	};
	
	/**
	 * A comparator for comparing Mobs by Location.
	 */
	public static Comparator<Mob> mobComparatorLocation = new Comparator<Mob>(){
		public int compare(final Mob first, final Mob second){
	    	if(first.getLocation()!=null && second.getLocation()==null){
	    		return 1;
	    	}else if(first.getLocation()==null && second.getLocation()==null){
	    		return 0;
	    	}else if(first.getLocation()==null && second.getLocation()!=null){
	    		return -1;
	    	}else{
	    		return (first.getLocation().getName()).compareTo(second.getLocation().getName());
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Groups by Number of members.
	 */
	public static Comparator<Group> groupComparatorCount = new Comparator<Group>(){
		public int compare(final Group first, final Group second){
	    	if(first.getBovineList().length > second.getBovineList().length){
	    		return 1;
	    	}else if(first.getBovineList().length == second.getBovineList().length){
	    		return 0;
	    	}else{
	    		return -1;
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Mobs by Number of members.
	 */
	public static Comparator<Mob> mobComparatorCount = new Comparator<Mob>(){
		public int compare(final Mob first, final Mob second){
	    	if(first.getBovineList().length > second.getBovineList().length){
	    		return 1;
	    	}else if(first.getBovineList().length == second.getBovineList().length){
	    		return 0;
	    	}else{
	    		return -1;
	    	}
	    }
	};
	
	/*
	 * Compare a list of Observations
	 */
	/**
	 * A comparator for comparing an Observation by Date.
	 */
	public static Comparator<Observation> observationComparatorDate = new Comparator<Observation>(){
		public int compare(final Observation first, final Observation second){
	        return ((Long)second.getDate().getTime()).compareTo(first.getDate().getTime());
	    }
	};
	
	/**
	 * A comparator for comparing Observation by Priority Status.
	 */
	public static Comparator<Observation> observationComparatorPriority = new Comparator<Observation>(){
		public int compare(final Observation first, final Observation second){
	    	if(first.getPriority() > second.getPriority()){
	    		return 1;
	    	}else if(first.getPriority() == second.getPriority()){
	    		return 0;
	    	}else{
	    		return -1;
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Observation by the owning owner type.
	 */
	public static Comparator<Observation> observationComparatorOwnerType = new Comparator<Observation>(){
		public int compare(final Observation first, final Observation second){
	    	Object oTf = first.getOwner();
	    	Object oTs = first.getOwner();
	    	return (oTf instanceof Bovine?"Cattle":oTf instanceof Paddock?"Paddock":oTf instanceof Location?"Location":oTf instanceof Mob?"Mob":oTf instanceof Group?"Group":"Unknown").compareTo(oTs instanceof Bovine?"Cattle":oTs instanceof Paddock?"Paddock":oTs instanceof Location?"Location":oTs instanceof Mob?"Mob":oTs instanceof Group?"Group":"Unknown");
	    }
	};
	
	/*
	 * Compare a list of Joinings
	 */
	/**
	 * A comparator for comparing Joinings by Entry Date.
	 */
	public static Comparator<Join> joiningComparatorEntry = new Comparator<Join>(){
		public int compare(final Join first, final Join second){
	    	return (first.getInsertionDate()).compareTo(second.getInsertionDate());
	    }
	};
	
	/**
	 * A comparator for comparing Joinings by Exit Date.
	 */
	public static Comparator<Join> joiningComparatorExit = new Comparator<Join>(){
		public int compare(final Join first, final Join second){
	    	if(first.getRemovalDate()!=null && second.getRemovalDate()==null){
	    		return 1;
	    	}else if(first.getRemovalDate()==null && second.getRemovalDate()==null){
	    		return 0;
	    	}else if(first.getRemovalDate()==null && second.getRemovalDate()!=null){
	    		return -1;
	    	}else{
	    		return (first.getRemovalDate()).compareTo(second.getRemovalDate());
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing Joinings by Bull Visual ID.
	 */
	public static Comparator<Join> joiningComparatorBull = new Comparator<Join>(){
		public int compare(final Join first, final Join second){
	    	return (first.getBull().getEartag().getEartagID()).compareTo(second.getBull().getEartag().getEartagID());
	    }
	};
	
	/**
	 * A comparator for comparing Joinings by Bull Visual ID.
	 */
	public static Comparator<Join> joiningComparatorCowCount = new Comparator<Join>(){
		public int compare(final Join first, final Join second){
	    	return (Integer.valueOf(first.getCows().length)).compareTo(second.getCows().length);
	    }
	};
	
	/*
	 * Compare a list of weighings for a particular cattle
	 */
	/**
	 * A comparator for comparing a Weighing by Date.
	 */
	public static Comparator<Weight> weighingComparatorDate = new Comparator<Weight>(){
		public int compare(final Weight first, final Weight second){
	        return ((Long)first.getDate().getTime()).compareTo(second.getDate().getTime());
	    }
	};
	
	/*
	 * Compare a list of UsableItemHistories
	 */
	/**
	 * A comparator for comparing a Usable Item History by Name.
	 */
	public static Comparator<UsableItemHistory> usableItemHistoryComparatorName = new Comparator<UsableItemHistory>(){
		public int compare(final UsableItemHistory first, final UsableItemHistory second){
	        return first.getItem().getName().compareTo(second.getItem().getName());
	    }
	};
	/**
	 * A comparator for comparing a Usable Item History by Date.
	 */
	public static Comparator<UsableItemHistory> usableItemHistoryComparatorDate = new Comparator<UsableItemHistory>(){
		public int compare(final UsableItemHistory first, final UsableItemHistory second){
	    	return first.getDate().compareTo(second.getDate());
	    }
	};
	/**
	 * A comparator for comparing a Usable Item History by Quantity.
	 */
	public static Comparator<UsableItemHistory> usableItemHistoryComparatorQty = new Comparator<UsableItemHistory>(){
		public int compare(final UsableItemHistory first, final UsableItemHistory second){
	    	int result=0;
	    	if((first.getMeasurement().equals("ml")&&second.getMeasurement().equals("l"))
	    	 ||(first.getMeasurement().equals("mg")&&(second.getMeasurement().equals("g")||second.getMeasurement().equals("kg")))
	    	 ||(first.getMeasurement().equals("g")&&second.getMeasurement().equals("kg"))){
	    		result=-1;
	    	}else if((second.getMeasurement().equals("ml")&&first.getMeasurement().equals("l"))
	    			||(second.getMeasurement().equals("mg")&&(first.getMeasurement().equals("g")||first.getMeasurement().equals("kg")))
	    			||(second.getMeasurement().equals("g")&&first.getMeasurement().equals("kg"))){
	    		result = 1;
	    	}else if((first.getMeasurement().equals("ml")||first.getMeasurement().equals("l")||first.getMeasurement().equals("mg")||first.getMeasurement().equals("g")||first.getMeasurement().equals("kg"))&&(second.getMeasurement().equals("ml")||second.getMeasurement().equals("l")||second.getMeasurement().equals("mg")||second.getMeasurement().equals("g")||second.getMeasurement().equals("kg"))){
	    		result = ((Double)first.getQuantity()).compareTo(second.getQuantity());
	    	}else{
	    		result = (first.getMeasurement().compareTo(second.getMeasurement()));
	    		if(result==0){
	    			result = ((Double)first.getQuantity()).compareTo(second.getQuantity());
	    		}
	    	}
	    	return result;
	    }
	};
	/**
	 * A comparator for comparing a Usable Item History by Purchase Date.
	 */
	public static Comparator<UsableItemHistory> usableItemHistoryComparatorPurchaseDate = new Comparator<UsableItemHistory>(){
		public int compare(final UsableItemHistory first, final UsableItemHistory second){
	    	return first.getItem().getPurchaseDate().compareTo(second.getItem().getPurchaseDate());
	    }
	};
	
	/*
	 * Compare a list of UsableItems
	 */
	/**
	 * A comparator for comparing a Usable Item History by Name.
	 */
	public static Comparator<UsableItem> usableItemComparatorName = new Comparator<UsableItem>(){
		public int compare(final UsableItem first, final UsableItem second){
	        return first.getName().compareTo(second.getName());
	    }
	};
	
	/**
	 * A comparator for comparing a Usable Item by Quantity Remaining.
	 * @deprecated Quantity has been moved to the UsableItemHistory, there is no more ability to determine qty remaining.
	 */
	public static Comparator<UsableItem> usableItemComparatorQtyLeft = new Comparator<UsableItem>(){
		public int compare(final UsableItem first, final UsableItem second){
	    	int result=0;
	    	/*
	    	if((first.getMeasurement().equals("ml")&&second.getMeasurement().equals("l"))
	    	 ||(first.getMeasurement().equals("mg")&&(second.getMeasurement().equals("g")||second.getMeasurement().equals("kg")))
	    	 ||(first.getMeasurement().equals("g")&&second.getMeasurement().equals("kg"))){
	    		result=-1;
	    	}else if((second.getMeasurement().equals("ml")&&first.getMeasurement().equals("l"))
	    			||(second.getMeasurement().equals("mg")&&(first.getMeasurement().equals("g")||first.getMeasurement().equals("kg")))
	    			||(second.getMeasurement().equals("g")&&first.getMeasurement().equals("kg"))){
	    		result = 1;
	    	}else if((first.getMeasurement().equals("ml")||first.getMeasurement().equals("l")||first.getMeasurement().equals("mg")||first.getMeasurement().equals("g")||first.getMeasurement().equals("kg"))&&(second.getMeasurement().equals("ml")||second.getMeasurement().equals("l")||second.getMeasurement().equals("mg")||second.getMeasurement().equals("g")||second.getMeasurement().equals("kg"))){
	    		result = ((Double)first.getQuantity()).compareTo(second.getQuantity());
	    	}else{
	    		result = (first.getMeasurement().compareTo(second.getMeasurement()));
	    		if(result==0){
	    			result = ((Double)(first.getQuantity()-first.getAmountUsed())).compareTo(second.getQuantity()-second.getAmountUsed());
	    		}
	    	}
	    	*/
	    	return result;
	    }
	};
	
	/**
	 * A comparator for comparing a Usable Item by Quantity.
	 */
	public static Comparator<UsableItem> usableItemComparatorQty = new Comparator<UsableItem>(){
		public int compare(final UsableItem first, final UsableItem second){
	    	int result=0;
	    	if((first.getMeasurement().equals("ml")&&second.getMeasurement().equals("l"))
	    	 ||(first.getMeasurement().equals("mg")&&(second.getMeasurement().equals("g")||second.getMeasurement().equals("kg")))
	    	 ||(first.getMeasurement().equals("g")&&second.getMeasurement().equals("kg"))){
	    		result=-1;
	    	}else if((second.getMeasurement().equals("ml")&&first.getMeasurement().equals("l"))
	    			||(second.getMeasurement().equals("mg")&&(first.getMeasurement().equals("g")||first.getMeasurement().equals("kg")))
	    			||(second.getMeasurement().equals("g")&&first.getMeasurement().equals("kg"))){
	    		result = 1;
	    	}else if((first.getMeasurement().equals("ml")||first.getMeasurement().equals("l")||first.getMeasurement().equals("mg")||first.getMeasurement().equals("g")||first.getMeasurement().equals("kg"))&&(second.getMeasurement().equals("ml")||second.getMeasurement().equals("l")||second.getMeasurement().equals("mg")||second.getMeasurement().equals("g")||second.getMeasurement().equals("kg"))){
	    		result = ((Double)first.getQuantity()).compareTo(second.getQuantity());
	    	}else{
	    		result = (first.getMeasurement().compareTo(second.getMeasurement()));
	    		if(result==0){
	    			result = ((Double)first.getQuantity()).compareTo(second.getQuantity());
	    		}
	    	}
	    	return result;
	    }
	};
	
	/**
	 * A comparator for comparing a Usable Item History by Purchase Date.
	 */
	public static Comparator<UsableItem> usableItemComparatorPurchaseDate = new Comparator<UsableItem>(){
		public int compare(final UsableItem first, final UsableItem second){
	    	return first.getPurchaseDate().compareTo(second.getPurchaseDate());
	    }
	};
	
	/*
	 * Compare a list of MedicalHistories
	 */
	/**
	 * A comparator for comparing a Medical Item History by Date.
	 */
	public static Comparator<MedicalHistory> medicalItemHistoryComparatorDate = new Comparator<MedicalHistory>(){
		public int compare(final MedicalHistory first, final MedicalHistory second){
	    	if(first.getDate()!=null && second.getDate()==null){
	    		return 1;
	    	}else if(first.getDate()==null && second.getDate()==null){
	    		return 0;
	    	}else if(first.getDate()==null && second.getDate()!=null){
	    		return -1;
	    	}else{
	    		return (first.getDate()).compareTo(second.getDate());
	    	}
	    }
	};
	
	/**
	 * A comparator for comparing a Medical Item History by number of applied medicines in the visit.
	 */
	public static Comparator<MedicalHistory> medicalItemHistoryComparatorCount = new Comparator<MedicalHistory>(){
		public int compare(final MedicalHistory first, final MedicalHistory second){
	    	return ((Integer)first.getPrescribedMedicines().length).compareTo(second.getPrescribedMedicines().length);
	    }
	};
	
	/**
	 * A comparator for comparing a Medical Item History by Cost.
	 */
	public static Comparator<MedicalHistory> medicalItemHistoryComparatorCost = new Comparator<MedicalHistory>(){
		public int compare(final MedicalHistory first, final MedicalHistory second){
	    	return ((Float)first.getCost()).compareTo(second.getCost());
	    }
	};
	
	/*
	 * Compare a list of Locations
	 */
	/**
	 * A comparator for comparing Locations by Name.
	 */
	public static Comparator<Location> locationComparatorName = new Comparator<Location>(){
		public int compare(final Location first, final Location second){
	    	return first.getName().compareTo(second.getName());
	    }
	};
	
	/*
	 * Compare a list of Paddocks
	 */
	/**
	 * A comparator for comparing Paddocks by Name.
	 */
	public static Comparator<Paddock> paddockComparatorName = new Comparator<Paddock>(){
		public int compare(final Paddock first, final Paddock second){
	    	return first.getName().compareTo(second.getName());
	    }
	};
	
	/**
	 * A comparator for comparing Paddocks by Area.
	 */
	public static Comparator<Paddock> paddockComparatorArea = new Comparator<Paddock>(){
		public int compare(final Paddock first, final Paddock second){
			int val = ((Integer)first.getUnits()).compareTo(second.getUnits());
			if(val==0){
				val = ((Double)first.getArea()).compareTo(second.getArea());
			}
			return val;
	    }
	};
	
	/**
	 * A comparator for comparing Paddocks by safe grazing date.
	 */
	public static Comparator<Paddock> paddockComparatorSafeGrazing = new Comparator<Paddock>(){
		public int compare(final Paddock first, final Paddock second){
	    	if(first.getSafeGrazingDate()!=null && second.getSafeGrazingDate()==null){
	    		return 1;
	    	}else if(first.getSafeGrazingDate()==null && second.getSafeGrazingDate()==null){
	    		return 0;
	    	}else if(first.getSafeGrazingDate()==null && second.getSafeGrazingDate()!=null){
	    		return -1;
	    	}else{
	    		return (first.getSafeGrazingDate()).compareTo(second.getSafeGrazingDate());
	    	}
	    }
	};
	
	/*
	 * Compare a list of Owners
	 */
	/**
	 * A Comparator for comparing Owners by Name.
	 */
	public static Comparator<Owner> ownerComparatorName = new Comparator<Owner>(){
		public int compare(final Owner first, final Owner second){
	        return first.getName().compareTo(second.getName());
	    }
	};
}